using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Oops.Xna.Framework.Physics;

namespace Oops.Xna.Framework.Testing.App
{
	public class Example4Screen : ExampleScreen
	{
		// Content.
		private Texture2D planeTexture;

		// Drawing helpers.
		private Quadrilateral quad;

		public Example4Screen(Game game)
			: base(game, "Example4")
		{
			// Drawing helper for the ground.
			this.quad = new Quadrilateral(Vector3.Zero, Vector3.Up, Vector3.Backward, 260.0f, 260.0f, 10, 10);
		}

		#region ExampleScreen Members

		protected override void DrawWorld(Effect effect, EffectParameter world, EffectParameter texture)
		{
			// Draw the ground.
			world.SetValue(Matrix.Identity);
			texture.SetValue(this.planeTexture);
			effect.CommitChanges();
			this.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, this.quad.Vertices, 0, 4, this.quad.Indices, 0, 2);
		}

		protected override void Reset()
		{
			// Reset the quad-tree and shape lists.
			this.boxes.Clear();
			this.spheres.Clear();

			// Clear the physics service of rigid bodies and static collision shapes.
			this.physics.RigidBodies.Clear();
			this.physics.CollisionSystem.CollisionGroups.Clear();

			// Seed the randomizer.
			Random random = new Random();

			for (int i = 0; i < 6; i++)
			{
				// Create the box.
				CollisionBox box = new CollisionBox();
				box.Extents = new Vector3(random.NextSingle(2.0f, 10.0f), 1.0f, 1.0f);
				box.Restitution = 0.6f;

				// Create a rigid body for the composite shape.
				RigidBody rigidBody = new RigidBody();

				// Add the box to the rigid body.
				rigidBody.CollisionGroup.CollisionShapes.Add(box);

				// Assign the box to the shape list.
				this.boxes.Add(box);

				// Iterate on all sphere shapes.
				for (int j = 0; j < 2; j++)
				{
					// Create the sphere and it's associated rigid body.
					CollisionSphere sphere = new CollisionSphere();
					sphere.Restitution = 0.8f;
					sphere.Radius = random.NextSingle(4.0f, 15.0f);
					sphere.OffsetPosition = new Vector3((j == 0 ? 1.0f : -1.0f) * (box.Extents.X + sphere.Radius), 0.0f, 0.0f);

					// Add the sphere to the rigid body.
					rigidBody.CollisionGroup.CollisionShapes.Add(sphere);

					// Assign the sphere to shape list.
					this.spheres.Add(sphere);
				}

				// Determine the position of the composite shape.
				Vector3 position = random.NextVector3(-90.0f, 90.0f, 150.0f, 170.0f, -90.0f, 90.0f);
#if QUATERNION_ORIENTATION
				Quaternion orientation = random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f);
#else
				Matrix orientation = Matrix.CreateFromQuaternion(random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f));
#endif
				//rigidBody.UpdateTransform(ref position, ref orientation);
				rigidBody.UpdateTransform(ref position);
				rigidBody.CalculateMassProperties(1.0f);

				rigidBody.Rotation = random.NextVector3(-1.30f, 1.30f);

				this.physics.RigidBodies.Add(rigidBody);
			}

			// Create the ground plane.  
			CollisionPlane plane = new CollisionPlane();
			plane.Normal = Vector3.UnitY;

			// Create a collision group and add the plane.
			CollisionGroup collisionGroup = new CollisionGroup();
			collisionGroup.CollisionShapes.Add(plane);

			// Add the plane's collision group to the collision system.
			this.physics.CollisionSystem.CollisionGroups.Add(collisionGroup);
		}

		#endregion

		#region DrawableGameComponent Members

		protected override void LoadContent()
		{
			// Load all the used texture resources.
			this.planeTexture = this.Game.GetContent().Load<Texture2D>(@".\Content\Textures\plane");

			// Call inherited method.
			base.LoadContent();
		}

		#endregion
	}
}

